package com.xy_pro.xymanager.auth.security;

import com.xy_pro.xymanager.entity.XYMessage;
import com.xy_pro.xymanager.service.UserDetailServiceImpl;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;

@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtTokenProvider tokenProvider;
    private final UserDetailServiceImpl userDetailsService;

    // 定义日志对象
    private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);

    // 忽略的路径列表（登录接口等无需 JWT 验证的路径）
    private List<String> ignorePaths = Arrays.asList("/api/auth/login");


    // 静态块，类加载时执行
//    static {
//        System.out.println("JwtAuthenticationFilter 类已加载！");
//        logger.debug("JwtAuthenticationFilter 类已加载！");
//    }

    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain
    ) throws ServletException, IOException {
        try {
            // 记录 CORS 响应头（注意：响应头在 filterChain.doFilter 后才会设置）
            // 建议移到 filterChain.doFilter 之后

            // 1. 检查是否为忽略的路径，若是则直接放行
            if (isIgnorePath(request.getRequestURI())) {
                filterChain.doFilter(request, response);
                return;
            }

            // 跳过 OPTIONS 请求
            if (HttpMethod.OPTIONS.matches(request.getMethod())) {
                filterChain.doFilter(request, response);
                return;
            }

            // 2. 解析 JWT 令牌
            XYMessage parseResult = parseJwt(request);
            if (parseResult.getCode() != 0) {
                sendErrorResponse(response, parseResult.getCode(), parseResult.getMessage());
                return;
            }

//            if (request instanceof HttpServletRequest) {
//                HttpServletRequest httpRequest = (HttpServletRequest) request;
//
//                // 记录请求URL和方法
//                logger.info("请求路径: {} {}", httpRequest.getMethod(), httpRequest.getRequestURI());
//
//                // 记录所有请求头
//                Enumeration<String> headerNames = httpRequest.getHeaderNames();
//                while (headerNames.hasMoreElements()) {
//                    String headerName = headerNames.nextElement();
//                    logger.info("请求头 - {}: {}", headerName, httpRequest.getHeader(headerName));
//                }
//            }

            String jwt = parseResult.getMessage();

            // 3. 验证 JWT 令牌
            XYMessage validateResult = tokenProvider.validateJwtToken(jwt);
            if (validateResult.getCode() != 0) {
                sendErrorResponse(response, validateResult.getCode(), validateResult.getMessage());
                return;
            }

            // 4. 从令牌中获取用户名并加载用户信息
            String username = tokenProvider.getUserNameFromJwtToken(jwt);
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);

            // 5. 创建并设置认证对象
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                    userDetails,
                    null,
                    userDetails.getAuthorities()
            );
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(authentication);

            // 6. 继续过滤器链
            filterChain.doFilter(request, response);

            // 记录 CORS 响应头（正确位置：响应生成后）
//            logger.debug("CORS 响应头 - Access-Control-Allow-Origin: {}", response.getHeader("Access-Control-Allow-Origin"));
//            logger.debug("CORS 响应头 - Access-Control-Allow-Methods: {}", response.getHeader("Access-Control-Allow-Methods"));
//            logger.debug("CORS 响应头 - Access-Control-Allow-Headers: {}", response.getHeader("Access-Control-Allow-Headers"));

        } catch (Exception e) {
            logger.error("JWT 认证异常", e);
            sendErrorResponse(response, HttpStatus.INTERNAL_SERVER_ERROR.value(), "JWT 认证失败");
        }
    }

    /**
     * 检查请求路径是否为需要忽略的路径（如登录接口）
     */
    private boolean isIgnorePath(String requestUri) {
        return ignorePaths.stream().anyMatch(requestUri::startsWith);
    }

    /**
     * 解析 JWT 令牌
     */
    private XYMessage parseJwt(HttpServletRequest request) {
        String headerAuth = request.getHeader("Authorization");
        XYMessage xyMessage = new XYMessage();

        String acc = request.getHeader("Content-Type");
//        logger.debug("Content-Type: {}", acc); // 使用日志输出代替 System.out
//
//        logger.debug("接收到的 Authorization 头: {}", headerAuth); // 使用日志输出代替 System.out
        if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
            xyMessage.setMessage(headerAuth.substring(7));
            xyMessage.setCode(0);
        } else {
            xyMessage.setCode(HttpStatus.UNAUTHORIZED.value());
            xyMessage.setMessage("未提供有效的 JWT 令牌");
        }

        return xyMessage;
    }

    /**
     * 发送错误响应
     */
    private void sendErrorResponse(HttpServletResponse response, int statusCode, String message) throws IOException {
        logger.warn("认证错误响应: {}", message); // 添加错误响应日志
        response.setStatus(statusCode);
        response.setContentType("application/json");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", statusCode);
        jsonObject.put("message", message);
        response.getWriter().write(jsonObject.toString());
    }

    /**
     * 设置需要忽略的路径（供外部配置）
     */
    public void setIgnorePaths(String... paths) {
        this.ignorePaths = Arrays.asList(paths);
    }
}